#include "config.h"
#include <stdint.h>

config_t g_config;

// 映射表定义，利用 offsetof() 获取字段偏移量
static const config_mapping_t config_mappings[] = {
    {"radar_server_port", CONFIG_INT16, offsetof(config_t, radar_server_port), sizeof(((config_t *)0)->radar_server_port), 0, 0},
    {"radar_client_port", CONFIG_INT16, offsetof(config_t, radar_client_port), sizeof(((config_t *)0)->radar_client_port), 0, 0},
    {"in_radar_ip", CONFIG_IP, offsetof(config_t, in_radar_ip), sizeof(((config_t *)0)->in_radar_ip), 0, 0},
    {"out_radar_ip", CONFIG_IP, offsetof(config_t, out_radar_ip), sizeof(((config_t *)0)->out_radar_ip), 0, 0},
    {"radar_link_mode", CONFIG_INT8, offsetof(config_t, radar_link_mode), sizeof(((config_t *)0)->radar_link_mode), 0, 0},

    {"in_radar_min_distance", CONFIG_INT16, offsetof(config_t, in_radar_min_distance), sizeof(((config_t *)0)->in_radar_min_distance), 0, 0},
    {"in_radar_max_distance", CONFIG_INT16, offsetof(config_t, in_radar_max_distance), sizeof(((config_t *)0)->in_radar_max_distance), 0, 0},
    {"in_radar_offset", CONFIG_INT16, offsetof(config_t, in_radar_offset), sizeof(((config_t *)0)->in_radar_offset), 0, 0},
    {"out_radar_min_distance", CONFIG_INT16, offsetof(config_t, out_radar_min_distance), sizeof(((config_t *)0)->out_radar_min_distance), 0, 0},
    {"out_radar_max_distance", CONFIG_INT16, offsetof(config_t, out_radar_max_distance), sizeof(((config_t *)0)->out_radar_max_distance), 0, 0},
    {"out_radar_offset", CONFIG_INT16, offsetof(config_t, out_radar_offset), sizeof(((config_t *)0)->out_radar_offset), 0, 0},
    {"radar_type", CONFIG_INT8, offsetof(config_t, radar_type), sizeof(((config_t *)0)->radar_type), 0, 0},

    {"video_server_port", CONFIG_INT16, offsetof(config_t, video_server_port), sizeof(((config_t *)0)->video_server_port), 0, 0},

    {"in_video_code", CONFIG_STRING, offsetof(config_t, in_video_device_code), sizeof(((config_t *)0)->in_video_device_code), 0, 0},
    {"out_video_code", CONFIG_STRING, offsetof(config_t, out_video_device_code), sizeof(((config_t *)0)->out_video_device_code), 0, 0},
    {"reference_lane", CONFIG_INT8, offsetof(config_t, reference_lane), sizeof(((config_t *)0)->reference_lane), 0, 0},
    {"scale_range", CONFIG_INT16_ARRAY, offsetof(config_t, scale_range), sizeof(((config_t *)0)->scale_range), 0, 0},

    {"incoming_near_focus_video_ip", CONFIG_IP, offsetof(config_t, incoming_near_focus_video_ip), sizeof(((config_t *)0)->incoming_near_focus_video_ip), 0, 0},
    {"incoming_far_focus_video_ip", CONFIG_IP, offsetof(config_t, incoming_far_focus_video_ip), sizeof(((config_t *)0)->incoming_far_focus_video_ip), 0, 0},
    {"outgoing_near_focus_video_ip", CONFIG_IP, offsetof(config_t, outgoing_near_focus_video_ip), sizeof(((config_t *)0)->outgoing_near_focus_video_ip), 0, 0},
    {"outgoing_far_focus_video_ip", CONFIG_IP, offsetof(config_t, outgoing_far_focus_video_ip), sizeof(((config_t *)0)->outgoing_far_focus_video_ip), 0, 0},

    {"video_center_x_ratio", CONFIG_DOUBLE, offsetof(config_t, video_center_x_ratio), sizeof(((config_t *)0)->video_center_x_ratio), 0, 0},
    {"time_diff_ms", CONFIG_INT16, offsetof(config_t, time_diff_ms), sizeof(((config_t *)0)->time_diff_ms), 0, 0},

    {"shanma_server_ip", CONFIG_IP, offsetof(config_t, shanma_server_ip), sizeof(((config_t *)0)->shanma_server_ip), 0, 0},
    {"shanma_server_port", CONFIG_INT16, offsetof(config_t, shanma_server_port), sizeof(((config_t *)0)->shanma_server_port), 0, 0},

    {"log_switch", CONFIG_INT8, offsetof(config_t, log_switch), sizeof(((config_t *)0)->log_switch), 0, 0},

    {"lane_num", CONFIG_INT8, offsetof(config_t, lane_num), sizeof(((config_t *)0)->lane_num), 0, 0},
    {"lane_id", CONFIG_INT8_ARRAY, offsetof(config_t, lane_id), sizeof(((config_t *)0)->lane_id), 0, 0},
    {"load_ruler_switch", CONFIG_INT8, offsetof(config_t, load_ruler_switch), sizeof(((config_t *)0)->load_ruler_switch), 0, 0},
    {"incoming_graduated_ruler", CONFIG_INT16_ARRAY, offsetof(config_t, incoming_graduated_ruler), sizeof(((config_t *)0)->incoming_graduated_ruler), 0, 0},
    {"outgoing_graduated_ruler", CONFIG_INT16_ARRAY, offsetof(config_t, outgoing_graduated_ruler), sizeof(((config_t *)0)->outgoing_graduated_ruler), 0, 0},
    {"change_lane_timeout", CONFIG_INT16, offsetof(config_t, change_lane_timeout), sizeof(((config_t *)0)->change_lane_timeout), 0, 0},
    {"incoming_obstacle_range", CONFIG_INT16_ARRAY, offsetof(config_t, incoming_obstacle_range), sizeof(((config_t *)0)->incoming_obstacle_range), 0, 0},
    {"outgoing_obstacle_range", CONFIG_INT16_ARRAY, offsetof(config_t, outgoing_obstacle_range), sizeof(((config_t *)0)->outgoing_obstacle_range), 0, 0},
    {"event_range", CONFIG_INT16, offsetof(config_t, event_range), sizeof(((config_t *)0)->event_range), 0, 0},

    {"in_lane_coordinate_1", CONFIG_INT32_STRUCT, offsetof(config_t, in_lane_coordinate[0]), sizeof(((config_t *)0)->in_lane_coordinate[0]), 0, 0},
    {"in_lane_coordinate_2", CONFIG_INT32_STRUCT, offsetof(config_t, in_lane_coordinate[1]), sizeof(((config_t *)0)->in_lane_coordinate[1]), 0, 0},
    {"in_lane_coordinate_3", CONFIG_INT32_STRUCT, offsetof(config_t, in_lane_coordinate[2]), sizeof(((config_t *)0)->in_lane_coordinate[2]), 0, 0},
    {"in_lane_coordinate_4", CONFIG_INT32_STRUCT, offsetof(config_t, in_lane_coordinate[3]), sizeof(((config_t *)0)->in_lane_coordinate[3]), 0, 0},
    {"in_lane_coordinate_5", CONFIG_INT32_STRUCT, offsetof(config_t, in_lane_coordinate[4]), sizeof(((config_t *)0)->in_lane_coordinate[4]), 0, 0},

    {"out_lane_coordinate_1", CONFIG_INT32_STRUCT, offsetof(config_t, out_lane_coordinate[0]), sizeof(((config_t *)0)->out_lane_coordinate[0]), 0, 0},
    {"out_lane_coordinate_2", CONFIG_INT32_STRUCT, offsetof(config_t, out_lane_coordinate[1]), sizeof(((config_t *)0)->out_lane_coordinate[1]), 0, 0},
    {"out_lane_coordinate_3", CONFIG_INT32_STRUCT, offsetof(config_t, out_lane_coordinate[2]), sizeof(((config_t *)0)->out_lane_coordinate[2]), 0, 0},
    {"out_lane_coordinate_4", CONFIG_INT32_STRUCT, offsetof(config_t, out_lane_coordinate[3]), sizeof(((config_t *)0)->out_lane_coordinate[3]), 0, 0},
    {"out_lane_coordinate_5", CONFIG_INT32_STRUCT, offsetof(config_t, out_lane_coordinate[4]), sizeof(((config_t *)0)->out_lane_coordinate[4]), 0, 0},

    {"relay_min_distance", CONFIG_INT16, offsetof(config_t, relay_min_distance), sizeof(((config_t *)0)->relay_min_distance), 0, 0},
    {"relay_max_distance", CONFIG_INT16, offsetof(config_t, relay_max_distance), sizeof(((config_t *)0)->relay_max_distance), 0, 0},
    {"candidate_relay_min_distance", CONFIG_INT16, offsetof(config_t, candidate_relay_min_distance), sizeof(((config_t *)0)->candidate_relay_min_distance), 0, 0},
    {"candidate_relay_max_distance", CONFIG_INT16, offsetof(config_t, candidate_relay_max_distance), sizeof(((config_t *)0)->candidate_relay_max_distance), 0, 0},

    {"pole_relay_max_distance", CONFIG_INT16, offsetof(config_t, pole_relay_max_distance), sizeof(((config_t *)0)->pole_relay_max_distance), 0, 0},
    {"pole_relay_min_distance", CONFIG_INT16, offsetof(config_t, pole_relay_min_distance), sizeof(((config_t *)0)->pole_relay_min_distance), 0, 0},
    {"pole_candidate_relay_min_distance", CONFIG_INT16, offsetof(config_t, pole_candidate_relay_min_distance), sizeof(((config_t *)0)->pole_candidate_relay_min_distance), 0, 0},
    {"pole_candidate_relay_max_distance", CONFIG_INT16, offsetof(config_t, pole_candidate_relay_max_distance), sizeof(((config_t *)0)->pole_candidate_relay_max_distance), 0, 0},

    {"pole_distance", CONFIG_INT16, offsetof(config_t, pole_distance), sizeof(((config_t *)0)->pole_distance), 0, 0},
    {"need_fusion", CONFIG_INT8, offsetof(config_t, need_fusion), sizeof(((config_t *)0)->need_fusion), 0, 0},

    {"video_debug", CONFIG_INT8, offsetof(config_t, video_debug), sizeof(((config_t *)0)->video_debug), 0, 0},
    {"struct_debug", CONFIG_INT8, offsetof(config_t, struct_debug), sizeof(((config_t *)0)->struct_debug), 0, 0},
    {"radar_debug", CONFIG_INT8, offsetof(config_t, radar_debug), sizeof(((config_t *)0)->radar_debug), 0, 0},
    {"fusion_debug", CONFIG_INT8, offsetof(config_t, fusion_debug), sizeof(((config_t *)0)->fusion_debug), 0, 0},
    {"event_debug", CONFIG_INT8, offsetof(config_t, event_debug), sizeof(((config_t *)0)->event_debug), 0, 0},

    {"upload_image_url", CONFIG_STRING, offsetof(config_t, upload_image_url), sizeof(((config_t *)0)->upload_image_url), 0, 0},
    {"need_send_pole", CONFIG_INT8, offsetof(config_t, need_send_pole), sizeof(((config_t *)0)->need_send_pole), 0, 0},
    {"need_third_relay", CONFIG_INT8, offsetof(config_t, need_third_relay), sizeof(((config_t *)0)->need_third_relay), 0, 0},
    {"need_pole_relay", CONFIG_INT8, offsetof(config_t, need_pole_relay), sizeof(((config_t *)0)->need_pole_relay), 0, 0},
};

static const size_t mapping_count = sizeof(config_mappings) / sizeof(config_mappings[0]);

// 辅助函数：去除字符串前后空白字符
static char *trim(char *str)
{
    while (isspace((unsigned char)*str)) str++;
    if (*str == '\0')
        return str;
    char *end = str + strlen(str) - 1;
    while (end > str && isspace((unsigned char)*end)) {
        *end = '\0';
        end--;
    }
    return str;
}

// 辅助函数：按指定分隔符分割字符串，返回下一个 token
char *get_next_token(char **str_ptr, char sep)
{
    if (*str_ptr == NULL)
        return NULL;
    char *start = *str_ptr;
    char *p = strchr(start, sep);
    if (p) {
        *p = '\0';
        *str_ptr = p + 1;
    }
    else {
        *str_ptr = NULL;
    }
    return trim(start);
}

void default_config(config_t *config)
{
    memset(config, 0, sizeof(config_t));
    config->scale_range[0] = 100;
    config->scale_range[1] = 150;
    config->scale_range[2] = 1420;
    config->event_range = 3000;
}

// 读取配置文件，更新 config_t 结构体中的参数
void read_config(const char *config_name, config_t *config)
{
    default_config(config);  // 初始化配置结构体

    FILE *fp = fopen(config_name, "r");
    if (!fp) {
        perror("打开配置文件失败");
        return;
    }

    char line[MAX_LINE_LEN];
    while (fgets(line, sizeof(line), fp)) {
        // 去除行末换行符
        line[strcspn(line, "\n")] = '\0';
        char *trimmed_line = trim(line);

        // 跳过空行或注释行（以 "//" 开头）
        if (strlen(trimmed_line) == 0 || strncmp(trimmed_line, "//", 2) == 0)
            continue;

        // 查找 '=' 分隔符
        char *equal_sign = strchr(trimmed_line, '=');
        if (!equal_sign) {
            // fprintf(stderr, "警告: 找不到 '='，忽略此行: %s\n", trimmed_line);
            continue;
        }
        *equal_sign = '\0';
        char *key = trim(trimmed_line);
        char *value = trim(equal_sign + 1);

        // 遍历映射表查找匹配的 key（使用 strcasecmp 实现不区分大小写）
        for (size_t i = 0; i < mapping_count; i++) {
            if (strcasecmp(key, config_mappings[i].key) == 0) {
                char *field = (char *)config + config_mappings[i].offset;
                switch (config_mappings[i].type) {
                    case CONFIG_INT8:
                        *((int8_t *)field) = atoi(value);
                        break;
                    case CONFIG_INT16:
                        *((int16_t *)field) = atoi(value);
                        break;
                    case CONFIG_INT32:
                        *((int32_t *)field) = atoi(value);
                        break;
                    case CONFIG_DOUBLE:
                        *((double *)field) = atof(value);
                        break;
                    case CONFIG_STRING:
                        strncpy((char *)field, value, config_mappings[i].size - 1);
                        ((char *)field)[config_mappings[i].size - 1] = '\0';
                        break;
                    case CONFIG_INT8_ARRAY: {
                        int count = 0;
                        char *token_ptr = value;
                        while (token_ptr && count < (int)config_mappings[i].size) {
                            char *token = get_next_token(&token_ptr, ',');
                            if (token && strlen(token) > 0) {
                                ((int8_t *)field)[count] = atoi(token);
                                count++;
                            }
                        }
                        if (config_mappings[i].count_offset) {
                            int *p_count = (int *)((char *)config + config_mappings[i].count_offset);
                            *p_count = count;
                        }
                        break;
                    }

                    case CONFIG_INT16_ARRAY: {
                        int count = 0;
                        char *token_ptr = value;
                        while (token_ptr && count < (int)config_mappings[i].size) {
                            char *token = get_next_token(&token_ptr, ',');
                            if (token && strlen(token) > 0) {
                                ((int16_t *)field)[count] = atoi(token);
                                count++;
                            }
                        }
                        if (config_mappings[i].count_offset) {
                            int *p_count = (int *)((char *)config + config_mappings[i].count_offset);
                            *p_count = count;
                        }
                        break;
                    }
                    case CONFIG_INT32_ARRAY: {
                        int count = 0;
                        // 直接在 value 上操作，不调用 strdup
                        char *token_ptr = value;
                        while (token_ptr && count < (int)config_mappings[i].size) {
                            char *token = get_next_token(&token_ptr, ',');
                            if (token && strlen(token) > 0) {
                                ((int *)field)[count] = atoi(token);
                                count++;
                            }
                        }
                        if (config_mappings[i].count_offset) {
                            int *p_count = (int *)((char *)config + config_mappings[i].count_offset);
                            *p_count = count;
                        }
                        break;
                    }
                    // 对于 CONFIG_DOUBLE_ARRAY 和 CONFIG_STRING_ARRAY 也类似：
                    case CONFIG_DOUBLE_ARRAY: {
                        int count = 0;
                        char *token_ptr = value;
                        while (token_ptr && count < (int)config_mappings[i].size) {
                            char *token = get_next_token(&token_ptr, ',');
                            if (token && strlen(token) > 0) {
                                ((double *)field)[count] = atof(token);
                                count++;
                            }
                        }
                        if (config_mappings[i].count_offset) {
                            int *p_count = (int *)((char *)config + config_mappings[i].count_offset);
                            *p_count = count;
                        }
                        break;
                    }
                    case CONFIG_STRING_ARRAY: {
                        int count = 0;
                        char *token_ptr = value;
                        while (token_ptr && count < (int)config_mappings[i].size) {
                            char *token = get_next_token(&token_ptr, ',');
                            if (token && strlen(token) > 0) {
                                char *dest = (char *)field + count * config_mappings[i].elem_size;
                                strncpy(dest, token, config_mappings[i].elem_size - 1);
                                dest[config_mappings[i].elem_size - 1] = '\0';
                                count++;
                            }
                        }
                        if (config_mappings[i].count_offset) {
                            int *p_count = (int *)((char *)config + config_mappings[i].count_offset);
                            *p_count = count;
                        }
                        break;
                    }
                    case CONFIG_IP: {
                        // 解析 IP 地址，直接在 value 上操作
                        unsigned char *ip = (unsigned char *)field;
                        printf("解析 IP 地址: key=%s, value=%s\n", key, value);
                        char *token_ptr = value;
                        int octet, count = 0;
                        while (token_ptr && count < 4) {
                            char *token = get_next_token(&token_ptr, '.');
                            if (token && strlen(token) > 0) {
                                octet = atoi(token);
                                if (octet < 0 || octet > 255) {
                                    fprintf(stderr, "警告: IP 地址无效的八位值: %s\n", token);
                                    break;
                                }
                                ip[count] = (unsigned char)octet;
                                count++;
                            }
                        }
                        if (count != 4) {
                            fprintf(stderr, "警告: IP 地址格式错误: %s\n", value);
                        }
                        break;
                    }
                    case CONFIG_INT32_STRUCT: {
                        int count = 0;
                        // 每个结构体占用两个 int，所以最大个数为 size / (2*sizeof(int))
                        int max = config_mappings[i].size / (2 * sizeof(int));
                        char *p = value;
                        while (p && count < max) {
                            // 查找下一个 '['
                            char *start = strchr(p, '[');
                            if (!start)
                                break;
                            start++;  // 跳过 '['
                            // 查找对应的 ']'
                            char *end = strchr(start, ']');
                            if (!end)
                                break;
                            *end = '\0';  // 将 ']' 替换为字符串结束符，便于解析内部数字

                            // 使用 get_next_token 按逗号分割解析两个整数
                            char *token = get_next_token(&start, ',');
                            if (token && strlen(token) > 0) {
                                ((int *)field)[count * 2] = atoi(token);
                            }
                            token = get_next_token(&start, ',');
                            if (token && strlen(token) > 0) {
                                ((int *)field)[count * 2 + 1] = atoi(token);
                            }
                            count++;

                            // 指针移动到当前 ']' 后面，跳过可能的逗号及空白字符
                            p = end + 1;
                            while (*p && (isspace((unsigned char)*p) || *p == ',')) {
                                p++;
                            }
                        }
                        // 如果配置映射中设置了计数偏移，则保存解析出的结构体个数
                        if (config_mappings[i].count_offset) {
                            int *p_count = (int *)((char *)config + config_mappings[i].count_offset);
                            *p_count = count;
                        }
                        break;
                    }

                    case CONFIG_DOUBLE_STRUCT: {
                        int count = 0;
                        // 每个结构体占用两个 double，所以最大个数为 size / (2*sizeof(double))
                        int max = config_mappings[i].size / (2 * sizeof(double));
                        char *p = value;
                        while (p && count < max) {
                            // 查找下一个 '['
                            char *start = strchr(p, '[');
                            if (!start)
                                break;
                            start++;  // 跳过 '['
                            // 查找对应的 ']'
                            char *end = strchr(start, ']');
                            if (!end)
                                break;
                            *end = '\0';  // 将 ']' 替换为字符串结束符，便于解析内部数字

                            // 使用 get_next_token 按逗号分割解析两个浮点数
                            char *token = get_next_token(&start, ',');
                            if (token && strlen(token) > 0) {
                                ((double *)field)[count * 2] = atof(token);
                            }
                            token = get_next_token(&start, ',');
                            if (token && strlen(token) > 0) {
                                ((double *)field)[count * 2 + 1] = atof(token);
                            }
                            count++;

                            // 指针移动到当前 ']' 后面，跳过可能的逗号及空白字符
                            p = end + 1;
                            while (*p && (isspace((unsigned char)*p) || *p == ',')) {
                                p++;
                            }
                        }
                        // 如果配置映射中设置了计数偏移，则保存解析出的结构体个数
                        if (config_mappings[i].count_offset) {
                            int *p_count = (int *)((char *)config + config_mappings[i].count_offset);
                            *p_count = count;
                        }
                        break;
                    }

                    default:
                        fprintf(stderr, "警告: 不支持的数据类型: %s\n", key);
                        break;
                }
                break;  // 找到匹配项后退出映射表遍历
            }
        }
    }
    fclose(fp);
}

char *format_config_value(config_type_t type, const void *new_value, int array_length,
                          size_t max_count, size_t elem_size, int struct_field_count)
{
    // 预分配足够缓冲区，实际项目中可根据情况动态计算
    char *buffer = malloc(4096);
    if (!buffer)
        return NULL;
    buffer[0] = '\0';

    switch (type) {
        case CONFIG_INT8:
            sprintf(buffer, "%d", *((int8_t *)new_value));
            break;
        case CONFIG_INT16:
            sprintf(buffer, "%d", *((int16_t *)new_value));
            break;
        case CONFIG_INT32:
            sprintf(buffer, "%d", *((int32_t *)new_value));
            break;
        case CONFIG_DOUBLE:
            sprintf(buffer, "%f", *((double *)new_value));
            break;
        case CONFIG_STRING:
            strncpy(buffer, (char *)new_value, 4095);
            buffer[4095] = '\0';
            break;
        case CONFIG_IP: {
            unsigned char *ip = (unsigned char *)new_value;
            sprintf(buffer, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
            break;
        }
        case CONFIG_INT8_ARRAY: {
            int8_t *arr = (int8_t *)new_value;
            for (int i = 0; i < array_length && i < (int)max_count; i++) {
                char temp[32];
                sprintf(temp, "%d", arr[i]);
                strcat(buffer, temp);
                if (i < array_length - 1)
                    strcat(buffer, ",");
            }
            break;
        }
        case CONFIG_INT16_ARRAY: {
            int16_t *arr = (int16_t *)new_value;
            for (int i = 0; i < array_length && i < (int)max_count; i++) {
                char temp[32];
                sprintf(temp, "%d", arr[i]);
                strcat(buffer, temp);
                if (i < array_length - 1)
                    strcat(buffer, ",");
            }
            break;
        }
        case CONFIG_INT32_ARRAY: {
            int *arr = (int *)new_value;
            for (int i = 0; i < array_length && i < (int)max_count; i++) {
                char temp[32];
                sprintf(temp, "%d", arr[i]);
                strcat(buffer, temp);
                if (i < array_length - 1)
                    strcat(buffer, ",");
            }
            break;
        }
        case CONFIG_DOUBLE_ARRAY: {
            double *arr = (double *)new_value;
            for (int i = 0; i < array_length && i < (int)max_count; i++) {
                char temp[64];
                sprintf(temp, "%f", arr[i]);
                strcat(buffer, temp);
                if (i < array_length - 1)
                    strcat(buffer, ",");
            }
            break;
        }
        case CONFIG_STRING_ARRAY: {
            // new_value 为连续内存区域，每个字符串占 elem_size 字节
            char *arr = (char *)new_value;
            for (int i = 0; i < array_length && i < (int)max_count; i++) {
                char *s = arr + i * elem_size;
                strcat(buffer, s);
                if (i < array_length - 1)
                    strcat(buffer, ",");
            }
            break;
        }
        case CONFIG_INT32_STRUCT: {
            // 结构体数组，数据类型为 int32，每个结构体包含 struct_field_count 个 int32
            int *arr = (int *)new_value;
            for (int i = 0; i < array_length && i < (int)max_count; i++) {
                char temp[256];
                temp[0] = '\0';
                strcat(temp, "[");
                for (int j = 0; j < struct_field_count; j++) {
                    char field_str[32];
                    sprintf(field_str, "%d", arr[i * struct_field_count + j]);
                    strcat(temp, field_str);
                    if (j < struct_field_count - 1)
                        strcat(temp, ",");
                }
                strcat(temp, "]");
                strcat(buffer, temp);
                if (i < array_length - 1)
                    strcat(buffer, ",");
            }
            break;
        }
        case CONFIG_DOUBLE_STRUCT: {
            // 结构体数组，数据类型为 double，每个结构体包含 struct_field_count 个 double
            double *arr = (double *)new_value;
            for (int i = 0; i < array_length && i < (int)max_count; i++) {
                char temp[256];
                temp[0] = '\0';
                strcat(temp, "[");
                for (int j = 0; j < struct_field_count; j++) {
                    char field_str[64];
                    sprintf(field_str, "%f", arr[i * struct_field_count + j]);
                    strcat(temp, field_str);
                    if (j < struct_field_count - 1)
                        strcat(temp, ",");
                }
                strcat(temp, "]");
                strcat(buffer, temp);
                if (i < array_length - 1)
                    strcat(buffer, ",");
            }
            break;
        }
        default:
            buffer[0] = '\0';
            break;
    }
    return buffer;
}

int update_config_file(const char *config_filename, const char *key, const void *new_value, int array_length, int struct_field_count)
{
    FILE *fin = fopen(config_filename, "r");
    if (!fin) {
        perror("打开配置文件失败");
        return -1;
    }

    char temp_filename[256];
    snprintf(temp_filename, sizeof(temp_filename), "%s.tmp", config_filename);
    FILE *fout = fopen(temp_filename, "w");
    if (!fout) {
        perror("打开临时文件失败");
        fclose(fin);
        return -1;
    }

    // 根据映射表查找 key 对应的类型
    config_type_t target_type = CONFIG_STRING;  // 默认
    size_t max_count = 0;                       // 对于数组或结构体数组，此处记录映射表中 size 字段
    size_t elem_size = 0;
    int found_in_mapping = 0;
    for (size_t i = 0; i < mapping_count; i++) {
        if (strcasecmp(key, config_mappings[i].key) == 0) {
            target_type = config_mappings[i].type;
            max_count = config_mappings[i].size;
            elem_size = config_mappings[i].elem_size;
            found_in_mapping = 1;
            break;
        }
    }
    // 如果未在映射表中找到，则默认认为 new_value 为字符串
    char *formatted_value = NULL;
    if (found_in_mapping) {
        formatted_value = format_config_value(target_type, new_value, array_length, max_count, elem_size, struct_field_count);
    }
    else {
        formatted_value = strdup((char *)new_value);
    }
    if (!formatted_value) {
        fclose(fin);
        fclose(fout);
        return -1;
    }

    char line[MAX_LINE_LEN];
    int key_found = 0;
    while (fgets(line, sizeof(line), fin)) {
        char orig_line[MAX_LINE_LEN];
        strncpy(orig_line, line, sizeof(orig_line));

        // 去掉行末换行符
        line[strcspn(line, "\n")] = '\0';
        char *trimmed_line = trim(line);

        // 空行或注释行直接写回
        if (strlen(trimmed_line) == 0 || strncmp(trimmed_line, "//", 2) == 0) {
            fprintf(fout, "%s", orig_line);
            continue;
        }

        // 查找 '=' 分隔符
        char *equal_sign = strchr(trimmed_line, '=');
        if (!equal_sign) {
            fprintf(fout, "%s", orig_line);
            continue;
        }
        *equal_sign = '\0';
        char *line_key = trim(trimmed_line);

        if (strcasecmp(line_key, key) == 0) {
            // 找到要更新的行，写入更新后的行（保留原有 key 格式）
            fprintf(fout, "%s = %s\n", line_key, formatted_value);
            key_found = 1;
        }
        else {
            // 其它行原样写回
            if (orig_line[strlen(orig_line) - 1] == '\n')
                fprintf(fout, "%s", orig_line);
            else
                fprintf(fout, "%s\n", orig_line);
        }
    }

    // 如果配置文件中没有该 key，则追加
    if (!key_found) {
        fprintf(fout, "%s = %s\n", key, formatted_value);
    }

    fclose(fin);
    fclose(fout);
    free(formatted_value);

    if (rename(temp_filename, config_filename) != 0) {
        perror("rename 更新配置文件失败");
        return -1;
    }
    return 0;
}

// 打印配置信息
void print_config(const config_t *config)
{
    int8_t i;
    printf("雷达服务器端口: %d\n", config->radar_server_port);
    printf("雷达客户端端口: %d\n", config->radar_client_port);
    printf("上行雷达 IP: %d.%d.%d.%d\n", config->in_radar_ip[0], config->in_radar_ip[1], config->in_radar_ip[2], config->in_radar_ip[3]);
    printf("下行雷达 IP: %d.%d.%d.%d\n", config->out_radar_ip[0], config->out_radar_ip[1], config->out_radar_ip[2], config->out_radar_ip[3]);
    printf("雷达连接模式: %d\n", config->radar_link_mode);
    printf("上行雷达最小距离: %d\n", config->in_radar_min_distance);
    printf("上行雷达最大距离: %d\n", config->in_radar_max_distance);
    printf("上行雷达偏移: %d\n", config->in_radar_offset);
    printf("视觉服务器端口: %d\n", config->video_server_port);
    printf("上行视频设备编码: %s\n", config->in_video_device_code);
    printf("下行视频设备编码: %s\n", config->out_video_device_code);
    printf("参考车道: %d\n", config->reference_lane);
    printf("视频中心 X 比例: %f\n", config->video_center_x_ratio);
    printf("闪马服务器 IP: %d.%d.%d.%d\n", config->shanma_server_ip[0], config->shanma_server_ip[1], config->shanma_server_ip[2], config->shanma_server_ip[3]);
    printf("闪马服务器端口: %d\n", config->shanma_server_port);
    printf("日志开关: %d\n", config->log_switch);
    printf("车道数量: %d\n", config->lane_num);
    printf("是否读取刻度尺: %d\n", config->load_ruler_switch);
    printf("接力车道误差最小值: %d\n", config->relay_min_distance);
    printf("接力车道误差最大值: %d\n", config->relay_max_distance);
    printf("候选接力车道误差最小值: %d\n", config->candidate_relay_min_distance);
    printf("候选接力车道误差最大值: %d\n", config->candidate_relay_max_distance);
    printf("延迟最小值:%dms\n", config->time_diff_ms);

    printf("事件调试: %d\n", config->event_debug);
    printf("视频调试: %d\n", config->video_debug);
    printf("雷达调试: %d\n", config->radar_debug);
    printf("融合调试: %d\n", config->fusion_debug);
    printf("结构化调试: %d\n", config->struct_debug);
    printf("变道超时: %d\n", config->change_lane_timeout);

    printf("是否融合: %d\n", config->need_fusion);

    printf("来向近焦视频 IP: %d.%d.%d.%d\n", config->incoming_near_focus_video_ip[0], config->incoming_near_focus_video_ip[1], config->incoming_near_focus_video_ip[2], config->incoming_near_focus_video_ip[3]);
    printf("来向远焦视频 IP: %d.%d.%d.%d\n", config->incoming_far_focus_video_ip[0], config->incoming_far_focus_video_ip[1], config->incoming_far_focus_video_ip[2], config->incoming_far_focus_video_ip[3]);
    printf("去向近焦视频 IP: %d.%d.%d.%d\n", config->outgoing_near_focus_video_ip[0], config->outgoing_near_focus_video_ip[1], config->outgoing_near_focus_video_ip[2], config->outgoing_near_focus_video_ip[3]);
    printf("去向远焦视频 IP: %d.%d.%d.%d\n", config->outgoing_far_focus_video_ip[0], config->outgoing_far_focus_video_ip[1], config->outgoing_far_focus_video_ip[2], config->outgoing_far_focus_video_ip[3]);

    printf("来向障碍物范围: start %d, end %d\n", config->incoming_obstacle_range[0], config->incoming_obstacle_range[1]);
    printf("去向障碍物范围: start %d, end %d\n", config->outgoing_obstacle_range[0], config->outgoing_obstacle_range[1]);

    printf("上传图片 URL: %s\n", config->upload_image_url);
    printf("标尺范围: 1 %d, 2 %d, 3 %d\n", config->scale_range[0], config->scale_range[1], config->scale_range[2]);
    printf("事件检测范围: %d\n", config->event_range);
    printf("雷达类型: %s\n", config->radar_type == 1 ? "北理工" : (config->radar_type == 2 ? "森斯泰克" : "未知"));
    printf("是否发送桩: %d\n", config->need_send_pole);
    printf("是否杆接力: %d\n", config->need_pole_relay);
}